package org.ucas.faker.web.utils.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.ucas.faker.web.utils.model.RawPatent;
import org.ucas.faker.web.dto.PageDto;
import org.ucas.faker.web.service.PatentService;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 万象云客户端
 */
@Component(value = "wxClient")
public class WxClient {
  private final static String CLIENT_ID = "wxy188c6e1a98b5af3f";

  private final static String CLIENT_SECRET = "9bd25739848c4d00aa35bea9c4105068";

  private String accessToken = null;

  private long expired = 3600;

  private WxParser parser = new WxParser();

  @Autowired
  PatentService patentService;

  public void authorize() {
    List<NameValuePair> params = new ArrayList<NameValuePair>() {{
      add(new BasicNameValuePair("client_id",CLIENT_ID));
      add(new BasicNameValuePair("client_secret",CLIENT_SECRET));
      add(new BasicNameValuePair("grant_type","client_credentials"));
    }};

    String res = HttpRequest.getInstance().doPost("https://oauth.wanxiangyun.net/open/token", params);
    JSONObject json = JSON.parseObject(res);

    if(Integer.valueOf(200).equals(json.getInteger("result_code"))) {
      accessToken = json.getString("access_token");
      expired = json.getLong("expires_in")/2;
    } else {
      accessToken = null;
      expired = 3;
    }
  }


  public PageDto<RawPatent> search(String query, Integer pageNumber) throws UnsupportedEncodingException {

    if(accessToken == null) authorize();

    List<NameValuePair> params = new ArrayList<NameValuePair>() {{
      add(new BasicNameValuePair("access_token",accessToken));
      add(new BasicNameValuePair("q", query));
      add(new BasicNameValuePair("mp", "false"));
      add(new BasicNameValuePair("ext", "false"));
    }};

    if(pageNumber != null) params.add(new BasicNameValuePair("page",pageNumber.toString()));

    String res = HttpRequest.getInstance().doPost("https://api.wanxiangyun.net/api/db/1/search/", params);
    System.out.println("res................:"+res);
    
    JSONObject json = JSON.parseObject(res);
    if(!Integer.valueOf(200).equals(json.getInteger("result_code"))) { authorize(); return null;}

    JSONObject data = json.getJSONObject("data");

    PageDto<RawPatent> page = new PageDto<>();
    page.pageSize = 20;
    page.page = pageNumber == null? 1 : pageNumber;
    page.totalSize = data.getLong("total_count");
    page.totalPages = (int) ((page.totalSize + 1) / 20);
    page.entries = new ArrayList<>();

    JSONArray arr = data.getJSONArray("patents");
    for(int i =0; i < arr.size(); ++i) {
      JSONObject item = arr.getJSONObject(i);
      RawPatent patent = parser.json(item).parseSearch();
      if(patent != null) page.entries.add(patent);
    }

    return page;
  }
  public PageDto<RawPatent> search(String q, String fq,Integer pageNumber,String mp,String ext,String sort) throws UnsupportedEncodingException {
	System.out.println("............................."+q);
    if(accessToken == null) authorize();

    List<NameValuePair> params = new ArrayList<NameValuePair>() {{
      add(new BasicNameValuePair("access_token",accessToken));
      add(new BasicNameValuePair("q", q));
    }};
    
    if(pageNumber != null) params.add(new BasicNameValuePair("page",pageNumber.toString()));
    if(sort!= null) params.add(new BasicNameValuePair("sort",sort));
    if(ext!= null) 
    	params.add(new BasicNameValuePair("ext",ext));
    else 
    	params.add(new BasicNameValuePair("ext","true"));
    if(mp!= null) 
    	params.add(new BasicNameValuePair("mp",mp));
    else
    	params.add(new BasicNameValuePair("mp","false"));
    if(fq != null) params.add(new BasicNameValuePair("fq",fq));
    String res = HttpRequest.getInstance().doPost("https://api.wanxiangyun.net/api/db/1/search/", params);
    System.out.println("res................:"+res);
    
    JSONObject json = JSON.parseObject(res);
    if(!Integer.valueOf(200).equals(json.getInteger("result_code"))) { authorize(); return null;}

    JSONObject data = json.getJSONObject("data");

    PageDto<RawPatent> page = new PageDto<>();
    page.pageSize = 20;
    page.page = pageNumber == null? 1 : pageNumber;
    page.totalSize = data.getLong("total_count");
    page.totalPages = (int) ((page.totalSize + 1) / 20);
    page.entries = new ArrayList<>();

    JSONArray arr = data.getJSONArray("patents");
    for(int i =0; i < arr.size(); ++i) {
      JSONObject item = arr.getJSONObject(i);
      RawPatent patent = parser.json(item).parseSearch();
      if(patent != null) page.entries.add(patent);
    }
    return page;
  }
  public RawPatent detail(String wxId) {
    List<NameValuePair> params = new ArrayList<NameValuePair>() {{
      add(new BasicNameValuePair("access_token",accessToken));
      add(new BasicNameValuePair("id",wxId));
    }};

    String res= HttpRequest.getInstance().doPost("https://api.wanxiangyun.net/api/db/detail/",params);
    JSONObject json = JSON.parseObject(res);

    if(!Integer.valueOf(200).equals(json.getInteger("result_code"))) {
    	System.out.println("Error Code");
    	return null;
    }

    return parser.json(json.getJSONObject("data")).parseDetail();
  }


  public Map<String,List> count(String query, Integer cnt, String... keys) {
	System.out.println("获取字段。。。。。。"+String.join(",",keys));
	if(cnt == null) cnt = 10;
    List<NameValuePair> params = new ArrayList<NameValuePair>(){{
      add(new BasicNameValuePair("access_token",accessToken));
      add(new BasicNameValuePair("q", query));
      add(new BasicNameValuePair("fl",String.join(",",keys)));
    }};
    params.add(new BasicNameValuePair("count",cnt.toString()));

    String res = HttpRequest.getInstance().doPost("https://api.wanxiangyun.net/api/db/1/analysis/composite/",params);
    JSONObject json = JSON.parseObject(res);
    System.out.println(json);
    if(!Integer.valueOf(200).equals(json.getInteger("result_code"))) return null;

    JSONObject data = json.getJSONObject("data");
    return parser.json(data).parseCount(Arrays.asList(keys));
  }

  public String getAccessToken() {
    return accessToken;
  }

  public long getExpired() {
    return expired;
  }

  public List<RawPatent> loadBatch(List<String> patentsId) {
		List<RawPatent> patents = new LinkedList<>();
		for(String each : patentsId) {
			RawPatent p = detail(each);
			patents.add(p);
		}
		return patents;
  }

  public List<WxPage> sync(String query, List<String> included, List<String> excluded) {
    if(query == null) {
      WxPage page = new WxPage(this);
      page.setToFetch(included);
      page.sync();
      return new ArrayList<WxPage>(){{
        add(page);
      }};
    } else {
      WxPage page = new WxPage(this,query,null);

      int retries = 3;
      while (page.getTotalPage() == null && retries > 0) {
        page.fetchMeta();
        --retries;
      }
      if(page.getTotalPage() == null) return null;
      List<WxPage> res = new ArrayList<>();
      Set<String> ids = excluded == null? null:new HashSet<>(excluded);
      for(int i = 1; i <= page.getTotalPage(); ++i) {
        page = new WxPage(this,query,i);
        if(ids != null) page.exclude(ids);
        page.sync();
        res.add(page);
      }
      return res;
    }
  }
}


